/*
 * TurdletBase.java
 *
 * Created on October 21, 2006, 1:25 AM
 *
 */

package tomkitty.turdlet;

import tomkitty.server.*;
import tomkitty.util.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * This is an abstract turdlet base class. It contains various methods and 
 * things to make turdlets easy to use. Inheriting from this class takes a 
 * lot of the boilerplate coding out of the process of creating a turdlet. 
 *
 * <p>
 *
 * Here is a simple example turdlet:
 *
 * <p>
 *
 * <pre>
 *    package mypackage;
 *    import tomkitty.turdlet.*;
 * 
 *    public class TurdletExample extends TurdletBase {
 *
 *      public void doit() {
 *        print("&lt;html&gt;");
 *        print("  &lt;head&gt;&lt;title&gt;Turdlet Example&lt;/title&gt;&lt;/head&gt;");
 *        print("  &lt;body&gt;");
 *        print("    &lt;center&gt;&lt;h1&gt;Hello, world!&lt;/h1&gt;&lt;/center&gt;");
 *        print("  &lt;/body&gt;");
 *        print("&lt;/html&gt;");
 *      }
 *
 *    }
 * </pre>
 *
 * @author micha
 */
public abstract class TurdletBase implements Turdlet {
    
		private boolean done = true;

		protected TurdletContext context;
    
		/**
		 * Sole constructor.  (For invocation by subclass constructors, 
		 * typically implicit.)
		 */
		protected TurdletBase() {
		}

    /**
 		 * Sets up the internal state of the turdlet. This method is called by
		 * the turdlet container, so don't pay too much attention to it unless
		 * you're going to override it.
		 */
    public void init(TurdletContext context) {
			this.context = context;
    }
    
		/**
		 * Gets the <code>TurdletContext</code> for this turdlet.
		 */
		public TurdletContext getContext() {
			return context;
		}

		/**
		 * Does it. This method is where the bulk of the stuff that's going to
		 * happen is located. This method is called by the turdlet container
		 * after the <code>init</code> method is called. Here is where you will
		 * write headers and print your html or whatever.
		 */
    public abstract void doit();

		/**
		 * Sets the turdlet to persistent mode, meaning the turdlet will not
		 * be destroyed after the <code>doit</code> method is finished. This
		 * is useful if you want to wait for an event, for example, to send
		 * more data to the client. In persistent mode the turdlet will keep
		 * the client 'loading' forever, or until the <code>done</code> method
		 * is called.
		 */
		protected void persist() {
			done = false;
		}
		
		/**
		 * Takes the turdlet out of persistent mode and marks it as ready for
		 * destruction or recycling.
		 */
		protected void done() {
			done = true;
		}

		/**
		 * Indicates whether the turdlet is in persistent mode or not. The turdlet
		 * container goes into a tight loop after the <code>doit</code> method
		 * finishes, and spins, calling this method until it returns <i>true</i>. 
		 * This method is only meant to be called by the turdlet container, so you 
		 * probably don't need to mess with it.
		 *
		 * @return <i>true</i> if this turdlet is ready to be destroyed/recycled
		 * 				 and <i>false</i> if not.
		 */
		public boolean isDone() {
				return done;
		}

		/**
		 * Sets the HTTP status code for the response, for example <i>200 OK</i>.
		 * This method must be called prior to sending any data with the
		 * <code>print</code> method or the <code>header</code> method, or it
		 * will have no effect. The default status code is <i>200 OK</i>, so
		 * you only need to call this method if you want something different than
		 * that.
		 *
		 * @param status the status code.
		 * @see HttpConstants
		 */
		public void setStatus(String status) {
			context.getOut().setStatus(status);
		}

		/**
		 * Sets the HTTP content type for the response, for example 
		 * <i>text/html</i>. This method must be called prior to sending any 
		 * data with the <code>print</code> method or the <code>header</code> 
		 * method, or it will have no effect. The default content type is
		 * <i>text/html</i>, so you only need to call this method if you want
		 * something different.
		 *
		 * @param contentType the content type.
		 */
		public void setContentType(String contentType) {
			context.getOut().setContentType(contentType);
		}

		/**
		 * Appends a line to the HTTP header. This method must be called before
		 * any data is sent with the <code>print</code> method, or it will have
		 * no effect.
		 *
		 * @param line the additional header line.
		 */
		public void header(String line) {
			context.getOut().header(line);
		}

		/**
		 * Sends data to the client. This method causes the HTTP headers to be
		 * sent before any data, so subsequent calls to <code>setStatus</code>,
		 * <code>setContentType</code>, or <code>header</code> will have no
		 * effect.
		 *
		 * @param data the string to send.
		 */
		protected void print(String data) {
			context.getOut().print(data);
		}
		
		protected void write(byte[] data, int off, int len) {
			context.getOut().write(data, off, len);
		}
		
		protected void write(int out) {
			context.getOut().write(out);
		}

		protected void setContentLength(int len) {
			context.getOut().setContentLength(len);
		}
}
